//
//  PMPinJoint.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 10/31/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMJoint for representing pin joints. A PMPinJoint Connects two 
 * PMBodys with a solid pin or rod. The ends of the "rod" are anchored to each 
 * body, keeping the two anchor points a set distance from each other.
 */

#import "PMPinJoint.h"
#import "PMBody.h"


@implementation PMPinJoint


#pragma mark -
#pragma mark Init

/**
 * Returns a PMPinJoint object initialized by anchoring two given rigid bodys at 
 * their center of gravity.
 */
- (id)initWithBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody {
	return [self initWithAnchor:PMVectZero 
						onBodyA:aBody 
						 anchor:PMVectZero 
						onBodyB:otherBody];
}

/**
 * Returns a PMPinJoint object initialized by anchoring two given rigid bodys at 
 * given positions reletive to the corresponding body's center of gravity.
 */
- (id)initWithAnchor:(PMVect)anchorA onBodyA:(PMBody *)aBody anchor:(PMVect)anchorB onBodyB:(PMBody *)otherBody {
	if (![super init])
		return nil;
	
	// allocate and initialize cpJoint
	joint = cpPinJointNew(aBody.cpBody, otherBody.cpBody, anchorA, anchorB);
	
	// set body references
	self.bodyA = aBody;
	self.bodyB = otherBody;
	
	return self;
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the receiver's joint anchor position for bodyA.
 */
- (PMAnchor)anchorA {
	return ((cpPinJoint *) joint)->anchr1;
}

/**
 * Returns the receiver's joint anchor position for bodyB.
 */
- (PMAnchor)anchorB {
	return ((cpPinJoint *) joint)->anchr2;
}

/**
 * Returns the receiver's joint anchor position for the body corresponding to the 
 * given key. Returns PMVectZero if there is no body/anchor for the given key.
 */
- (PMAnchor)anchorForBodyWithKey:(PMJointBodyKey)bodyKey {
	switch (bodyKey) {
		case PMJointBodyKeyA:
			return [self anchorA];
		case PMJointBodyKeyB:
			return [self anchorB];
		default:
			return PMVectZero;
	}
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the joint anchor position of the receiver's bodyA to a given point relative
 * the the body's center of gravity.
 */
- (void)setAnchorA:(PMAnchor)anchor {
	((cpPinJoint *) joint)->anchr1 = anchor;
}

/**
 * Sets the joint anchor position of the receiver's bodyB to a given point relative
 * the the body's center of gravity.
 */
- (void)setAnchorB:(PMAnchor)anchor {
	((cpPinJoint *) joint)->anchr2 = anchor;
}

/**
 * Sets the joint anchor position of the receiver's body corresponding to the given
 * key, to a given point relative the the body's center of gravity.
 */
- (void)setAnchor:(PMAnchor)anchor ForBodyWithKey:(PMJointBodyKey)bodyKey {
	switch (bodyKey) {
		case PMJointBodyKeyA:
			return [self setAnchorA:anchor];
		case PMJointBodyKeyB:
			return [self setAnchorB:anchor];
	}
}

@end
